package com.heima.utils.common;

import java.util.regex.Pattern;

/**
 * 正则表达式工具类 - 严格校验
 */
public class RegexUtil {

    // 账号校验：4-16位字母/数字/下划线，禁用特殊符号 
    private static final Pattern ACCOUNT_PATTERN = 
        Pattern.compile("^[a-zA-Z0-9_]{4,16}$");

    // 昵称校验：中文2-8字 或 英文2-16字符（允许空格）
    private static final Pattern NICKNAME_PATTERN = 
        Pattern.compile("^(?:[\\u4e00-\\u9fa5]{2,8}|[a-zA-Z\\s]{2,16})$");

    // 座机：区号3-4位+号码7-8位，分隔符必需
    private static final Pattern LANDLINE_PATTERN = 
        Pattern.compile("^0\\d{2,3}-[1-9]\\d{6,7}$");

    // 身份证：15位数字或18位数字+X校验码 
    private static final Pattern ID_CARD_PATTERN = Pattern.compile(
        "(^\\d{15}$)|(^\\d{17}([0-9Xx])$)");

    // 邮编：中国标准6位数字
    private static final Pattern ZIPCODE_PATTERN = 
        Pattern.compile("^[1-9]\\d{5}$");

    // 邮箱：兼容企业邮箱和多级域名
    private static final Pattern EMAIL_PATTERN = 
        Pattern.compile("^(\\w+)(\\.\\w+)*@(\\w+\\.)+[a-zA-Z]{2,7}$");

    // QQ号：5-12位数字，非0开头 
    private static final Pattern QQ_PATTERN = 
        Pattern.compile("^[1-9]\\d{4,11}$");



    // URL：包含协议头验证
    private static final Pattern URL_PATTERN = 
        Pattern.compile("^(https?|ftp)://[^\\s/$.?#].[^\\s]*$");
    // 手机号：严格13位且符合运营商号段
    private static final Pattern MOBILE_PATTERN =
            Pattern.compile("^1[3-9]\\d{9}$");
    // 密码：强制大小写+数字+特殊符号，8-20位
    private static final Pattern PASSWORD_PATTERN =
            Pattern.compile("^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@#$%^&*!~])[\\w@#$%^&*!~]{8,20}$");


    // ================= 校验方法 ================= 
    /**
     * 检查输入字符串是否为有效的账号格式
     * @param input 待校验的账号字符串
     * @return 如果符合账号格式则返回true，否则返回false
     */
    public static boolean isValidAccount(String input) {
        return ACCOUNT_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的昵称格式
     * @param input 待校验的昵称字符串
     * @return 如果符合昵称格式则返回true，否则返回false
     */
    public static boolean isValidNickname(String input) {
        return NICKNAME_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的手机号格式
     * @param input 待校验的手机号字符串
     * @return 如果符合手机号格式则返回true，否则返回false
     */
    public static boolean isValidMobile(String input) {
        return MOBILE_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的座机号格式
     * @param input 待校验的座机号字符串
     * @return 如果符合座机号格式则返回true，否则返回false
     */
    public static boolean isValidLandline(String input) {
        return LANDLINE_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的身份证号格式，并进行校验码验证
     * @param input 待校验的身份证号字符串
     * @return 如果符合身份证号格式且校验码正确则返回true，否则返回false
     */
    public static boolean isValidIdCard(String input) {
        if (!ID_CARD_PATTERN.matcher(input).matches()) {
            return false;
        }
        // 校验码算法见补充说明
        return IdCardValidator.checkLastDigit(input);
    }

    /**
     * 检查输入字符串是否为有效的密码格式
     * @param input 待校验的密码字符串
     * @return 如果符合密码格式则返回true，否则返回false
     */
    public static boolean isValidPassword(String input) {
        return PASSWORD_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的邮政编码格式
     * @param input 待校验的邮政编码字符串
     * @return 如果符合邮政编码格式则返回true，否则返回false
     */
    public static boolean isValidZipcode(String input) {
        return ZIPCODE_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的邮箱格式
     * @param input 待校验的邮箱字符串
     * @return 如果符合邮箱格式则返回true，否则返回false
     */
    public static boolean isValidEmail(String input) {
        return EMAIL_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的QQ号格式
     * @param input 待校验的QQ号字符串
     * @return 如果符合QQ号格式则返回true，否则返回false
     */
    public static boolean isValidQQ(String input) {
        return QQ_PATTERN.matcher(input).matches();
    }

    /**
     * 检查输入字符串是否为有效的URL格式
     * @param input 待校验的URL字符串
     * @return 如果符合URL格式则返回true，否则返回false
     */
    public static boolean isValidURL(String input) {
        return URL_PATTERN.matcher(input).matches();
    }

    /**
     * 身份证校验码验证工具类
     */
    private static class IdCardValidator {
        /**
         * 根据身份证前17位计算校验码并比对第18位
         * @param id 完整的18位身份证号码
         * @return 如果校验码匹配返回true，否则返回false
         */
        static boolean checkLastDigit(String id) {
            if (id.length() != 18) {
                return true;
            }
            char[] chars = id.toCharArray();
            int[] factor = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
            char[] parity = {'1','0','X','9','8','7','6','5','4','3','2'};
            int sum = 0;
            for (int i = 0; i < 17; i++) {
                sum += (chars[i] - '0') * factor[i];
            }
            return parity[sum % 11] == Character.toUpperCase(chars[17]);
        }
    }

    /**
     * 检测密码强度等级（0-3级）
     * @param pwd 待检测的密码字符串
     * @return 密码强度等级：0表示无效密码，1-3表示不同强度等级
     */
    public static int checkPasswordStrength(String pwd) {
        if (!isValidPassword(pwd)) {
            return 0;
        }
        int strength = 0;
        if (pwd.length() >= 12) {
            strength++;       // 长度加分
        }
        if (Pattern.compile("[@#$%^&*!~]").matcher(pwd).find()) {
            strength++; // 特殊符号
        }
        if (Pattern.compile("\\d{3,}").matcher(pwd).find()) {
            strength++;     // 连续数字
        }
        return Math.min(strength, 3);
    }
}
